﻿'===============================================================
'Lucene Manager 
'---------------------------------------------------------------
'Purpose : Indexes the jobOffer reconds. Class is responsible for  
'          findind the job offers based on their descriptions.
'          Free-text searching.
'          
'
' Author : John Paraskevopoulos, 8 December 2012
'===============================================================

Imports Lucene.Net
Imports Lucene.Net.Documents
Imports Lucene.Net.Analysis.Standard
Imports Lucene.Net.Store
Imports Lucene.Net.Index
Imports Lucene.Net.Search
Imports System.Data.OleDb

Public Class LuceneManager

    Private analyzer As StandardAnalyzer = New StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_29)
    Private indexDR As Directory = New RAMDirectory
    Private writer As IndexWriter = New IndexWriter(indexDR, analyzer, True, IndexWriter.MaxFieldLength.LIMITED)
    Private indexReader As IndexReader
    Private indexSearcher As Searcher

    '===============================================================
    'LuceneManager - public Sub constructor
    '---------------------------------------------------------------
    'Purpose : Runs through all the records of (JobOffer) table in DB
    '          and puts the data to indexDR (RAMDirectory)
    '          Uses private sub addDoc to add documents to index 
    '          Uses public finction close to close the connetion to indexDR 
    '
    ' Author : John Paraskevopoulos, 3 January 2012
    '===============================================================
    Public Sub New()
        Dim query1 As String = "SELECT * FROM JobOffer"

        Dim cn As OleDb.OleDbConnection = New OleDbConnection
        Dim cmd As New OleDbCommand
        Dim dtJobOffer As DataTable = New DataTable
        Dim tempDoc As Document = New Document()

        Try
            cn.ConnectionString = My.Settings.DatabaseConnectionString
            cn.Open()

            cmd.Connection = cn
            cmd.CommandType = CommandType.Text
            cmd.CommandText = query1
            Dim oleAd As OleDbDataAdapter = New OleDbDataAdapter(cmd)

            oleAd.Fill(dtJobOffer)
            Dim tempStr As String = ""


            For Each row In dtJobOffer.Rows
                'tempStr += row.Item("JobOfferID").ToString + " " + row.Item("JobOfferDescription").ToString + Environment.NewLine
                'addDoc(CType(row.Item("JobOfferID"), Int16), row.Item("JobOfferDescription").ToString)
                addDoc(row)
            Next

            'MessageBox.Show(tempStr)

        Catch ex As Exception
            MessageBox.Show("Cannot retrieve the offers - JMatcher class!!!" & ex.Message, "Connection to Database Error")
        Finally
            cn.Close()
            close()
        End Try
    End Sub

    '===============================================================
    'LuceneManager - public Sub addDoc
    '---------------------------------------------------------------
    'Purpose : Adds a document to the index
    '          Inputs a JobOffer row 
    '               (Id) : which is not ANALYZED by LUCENE
    '               (EmployerId) : which is not ANALYZED by LUCENE
    '               (Description) : which is ANALYZED by LUCENE
    '
    ' Author : John Paraskevopoulos, 3 January 2012
    '===============================================================
    Public Sub addDoc(ByVal row As DataRow)

        Dim tempDoc As Document = New Document()
        tempDoc.Add(New Field("Id", row.Item("JobOfferID"), Field.Store.YES, Field.Index.NOT_ANALYZED))
        tempDoc.Add(New Field("EmployerId", row.Item("JobOfferEmployerUserID"), Field.Store.YES, Field.Index.NOT_ANALYZED))
        tempDoc.Add(New Field("Description", row.Item("JobOfferDescription"), Field.Store.YES, Field.Index.ANALYZED))
        writer.AddDocument(tempDoc)

    End Sub

    '===============================================================
    'LuceneManager - public Sub close
    '---------------------------------------------------------------
    'Purpose : Optimize the indexes : Semi-equivalent to defragment of indexes
    '          And closes the indexes, ready for searching
    '
    ' Author : John Paraskevopoulos, 3 January 2012
    '===============================================================
    Public Sub close()
        writer.Optimize()
        writer.Close()
        indexReader = indexReader.Open(indexDR, True)
        indexSearcher = New IndexSearcher(indexReader)
    End Sub

    '===============================================================
    'LuceneManager - public Function findOffers
    '---------------------------------------------------------------
    'Purpose : Creating a query
    '          QueryParser specifies the field we want to search
    '          Query is defined by the function's argument
    '          Returns a datatable (job's description, employer's id)  
    '           
    ' Author : John Paraskevopoulos, 3 January 2012
    '===============================================================
    Public Function findOffers(ByVal queryStr As String) As DataTable

        Dim queryParser As QueryParsers.QueryParser = New QueryParsers.QueryParser(Lucene.Net.Util.Version.LUCENE_29, "Description", analyzer)
        Dim query As Query = queryParser.Parse(queryStr)

        Dim resultsDocs As TopDocs = indexSearcher.Search(query, indexReader.MaxDoc)
        Dim allDocs As ScoreDoc() = resultsDocs.scoreDocs

        ' Creating datatable for output values
        Dim result As DataTable = New DataTable("Results")
        Dim col1 As DataColumn = New DataColumn("JobOfferID")
        col1.DataType = System.Type.GetType("System.Int32")
        Dim col2 As DataColumn = New DataColumn("JobOfferDescription")
        col2.DataType = System.Type.GetType("System.String")
        Dim col3 As DataColumn = New DataColumn("JobOfferEmployerUserID")
        col3.DataType = System.Type.GetType("System.Int32")
        
        result.Columns.Add(col1)
        result.Columns.Add(col2)
        result.Columns.Add(col3)

        For Each hit As ScoreDoc In allDocs
            Dim tempDocument As Document = indexSearcher.Doc(hit.doc)
            Dim tempRow As DataRow = result.NewRow
            tempRow.Item(0) = tempDocument.Get("Id")
            tempRow.Item(1) = tempDocument.Get("Description")
            tempRow.Item(2) = tempDocument.Get("EmployerId")
            result.Rows.Add(tempRow)
        Next

        Return result
    End Function

End Class

